#include "StringUtil.h"
#include <string.h>
#include "Log/Log.h"
#include "Poco/RegularExpression.h"

using namespace std;

std::string StringUtil::Date2String(DATE_FMT fmt)
{
    try
    {
        Poco::LocalDateTime dt;
        return Date2String(dt, fmt);
    }
    catch (...)
    {
        return "";
    }
}

std::string StringUtil::Date2String(Poco::LocalDateTime dt, DATE_FMT fmt)
{
    char buf[100];
    memset(buf, 0, 100);
    if (fmt == DATE_FMT_LOG)
    {
        sprintf(buf, "[%04d-%02d-%02d %02d:%02d:%02d.%03d%03d] ", dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute(), dt.second(), dt.millisecond(), dt.microsecond());//用于日志
    }
    else if (fmt == DATE_FMT_LOG_FILENAME)
    {
        sprintf(buf, "%04d-%02d-%02d_%02d-%02d-%02d", dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute(), dt.second());
    }
    else
    {
        sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%03d", dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute(), dt.second(), dt.millisecond());
    }
    return string(buf);
}

std::string StringUtil::Int2String(int i)
{
    char buf[100];
    memset(buf, 0, 100);
    sprintf(buf, "%0d", i);
    return string(buf);
}

std::string StringUtil::HexFormat(const char* buf, int iLen)
{
    /*
     * char a[7];
     * a[0] = 0x23;
     * a[1] = 0x45;
     * a[2] = 0x67;
     * 打印
     * 23 45 67                                           #Eg
     */
    std::string strHexFormat = "Hex = \n\n";
    std::string strHex, strChar;
    for (int i = 0; i < iLen; ++i)
    {
        strHex += (Hex2String((unsigned char)buf[i]) + ' ');
        if (buf[i] >= 0x20 && buf[i] <= 0x7e)
        {
            strChar.push_back(buf[i]);
        }
        else
        {
            strChar.push_back('.');
        }
        if ((i % 8 == 7) && (i % 16) != 15)
        {
            strHex.push_back(' ');
            strChar.push_back(' ');
        }
        if (i % 16 == 15)
        {
            strHexFormat += strHex + "  " + strChar + '\n';
            strHex.clear();
            strChar.clear();
        }
    }
    if (strHex.empty() == false)
    {
        for (; strHex.size() < 49;)
        {
            strHex.push_back(' ');
        }
        strHexFormat += strHex + "  " + strChar + '\n';
    }
    return strHexFormat;
}

int StringUtil::String2Int(std::string s)
{
    int i;
    sscanf(s.c_str(), "%d", &i);
    return i;
}

bool StringUtil::String2Int(std::string s, int& i)
{
    Poco::RegularExpression re("[^0-9-]");
    Poco::RegularExpression::Match match;
    if (!re.match(s, 0, match))
    {
        i = String2Int(s);
        return true;
    }
    zlog.SError("String2Int fail, s = [%s]\n", s.c_str());
    return false;
}

int StringUtil::String2Hex(std::string s)
{
    int iHex = 0;
    for (size_t i = 0; i < s.size(); ++i)
    {
        int tmp;
        if (s[i] >= '0' && s[i] <= '9')
        {
            tmp = s[i] - '0';
        }
        else if (s[i] >= 'a' && s[i] <= 'z')
        {
            tmp = s[i] - 'a' + 0xa;
        }
        else if (s[i] >= 'A' && s[i] <= 'Z')
        {
            tmp = s[i] - 'A' + 0xa;
        }
        else
        {
            return -1;
        }
        iHex <<= 4;
        iHex |= tmp;
    }
    return iHex;
}

std::string StringUtil::Char2String(const char* c)
{
    if (c)
    {
        return std::string(c);
    }
    return "";
}

int StringUtil::Char2Int(const char* c)
{
    if (c)
    {
        return String2Int(Char2String(c));
    }
    return 0;
}

bool StringUtil::IsAllSpace(const std::string& str)
{
    for (size_t i = 0; i < str.size(); ++i)
    {
        if (str[i] != ' ')
        {
            return false;
        }
    }
    return true;
}

void StringUtil::RemoveSubString(std::string& strSrc, std::string strSubStr)
{
    std::string::size_type i;
    while ((i = strSrc.find(strSubStr)) != std::string::npos)
    {
        strSrc.erase(i, strSubStr.size());
    }
}

void StringUtil::StringReplace(std::string& str, std::string strSrc, std::string strDst)
{
    std::string::size_type i;
    while ((i = str.find(strSrc)) != std::string::npos)
    {
        str.replace(i, strSrc.size(), strDst.c_str());
    }
}

bool StringUtil::IsIP(std::string strIP)
{
    Poco::RegularExpression re("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
    Poco::RegularExpression::Match match;
    if (!re.match(strIP, 0, match))
    {
        return false;
    }
    return true;
}

int StringUtil::GetValueByKey(const std::string &s, const std::string &key, std::string &value, const std::string &endID)
{
    int iIndex = s.find(key);
    if (iIndex == string::npos)
    {
        zlog.SError("not find key [%s]\n", key.c_str());
        return -1;
    }
    string ns = s.substr(iIndex + key.size());
    iIndex = ns.find('=');
    if (iIndex == string::npos)
    {
        zlog.SError("not find '='\n");
        return -1;
    }
    ns = ns.substr(iIndex + 1);
    if (endID.empty() == false)
    {
        iIndex = ns.find(endID);
        if (iIndex != string::npos)
        {
            ns = ns.substr(0, iIndex);
        }
        else
        {
            zlog.SWarn("not find end [%s] for key [%s] in [%s]\n", endID.c_str(), key.c_str(), s.c_str());
        }
    }
    value = ns;
    return 0;
}

std::string StringUtil::Hex2String(unsigned char c)
{
    char res[3];
    res[0] = HarfHex2Byte(c >> 4);
    res[1] = HarfHex2Byte(c & 0xf);
    res[2] = 0;
    return string(res);
}

char StringUtil::HarfHex2Byte(unsigned char hh)
{
    if (hh >= 0 && hh <= 9)
    {
        return hh + '0';
    }
    else
    {
        return hh - 10 + 'A';
    }
}
